與前一個專案相同,大家應該都已經把layout大致刻好了,如果沒有也沒關係,可以使用我這個commit的程式碼:
https://github.com/yuanchen1103/2020ironman-github-contributions/commit/f44e65beba1195e15d3ea471fd7e3628d08b86fa
我們今天要使用的api文件在這裡:https://github.com/sallar/github-contributions-api
一般如果我們想要拿github的資料需要透過官方的api( https://developer.github.com/v3/ ),仔細研讀過後發現,若是要拿我們這次要使用的資料,可能需要申請一些權限,也要打好幾隻api才能整理出來,而我找到的這個人他已經幫我們整理好了,所以我們就直接拿來使用。這個api使用非常簡單:
GET https://github-contributions-api.now.sh/v1/GITHUB_USERNAME
我們可以拿自己的帳號來試打看看回傳的資料結構:
{
years: [
{
year: '2019',
total: 922,
...
},
...
],
contributions: [
{
date: '2019-12-31',
count: 0,
...
},
...
]
}
接著我們就可以使用前端來打api,在按下按鈕的時候會觸發一個getData
的function,並把使用者輸入的帳號加到網址中
const [input, setInput] = useState(''); // user input
const [data, setData] = useState(null); // response
const [isLoading, setIsLoading] = useState();
const getData = useCallback(() => {
if (!input.length) return; //沒有輸入的時候return
setIsLoading(true); //開始loading
axios
.get(`https://github-contributions-api.now.sh/v1/${input}`)
.then((res) => {
setIsLoading(false); //停止loading
setData(res.data); //把資料存起來
})
.catch((err) => {
setIsLoading(false);
setData(null);
console.error(err);
});
}, [input]);
知道了資料結構以後,我們就可以開始思考要怎麽裝進去我們的熱力圖裡面,因為我們一張熱力圖最多就是裝一年份的資料,且我們拿到的資料,都一定會有完整一年份的,因此我們就根據年來分組就可以了。
為了保持App.js的乾淨,我新建了一份js檔案來放跟算資料有關的function,這個資料我希望能是一個以年份為key的物件,值是那一年的陣列資料。
export const groupDataByYear = (data) => {
const arr = data.contributions;
const result = {};
for (let i = 0; i < arr.length; i += 1) {
const year = moment(arr[i].date).format('YYYY');
if (!result[year]) {
result[year] = [];
}
result[year].push({
value: arr[i].count || 0,
weekNum:
momentObj.weekYear() === Number(year)
? momentObj.week()
: momentObj.week() + moment(`${year}-01-01`).weeksInYear(),
day: momentObj.day(),
date: momentObj.format('YYYY-MM-DD'),
weekYear: momentObj.weekYear()
});
}
return result;
}
在App.js
中引進這個計算的函式,並產生各自的熱力圖:
const renderHeatMap = useCallback(() => {
const groupData = groupDataByYear(data);
return Object.keys(groupData)
.sort()
.reverse() //照倒反的年份順序排
.map((year) => (
<div className="heatmap-wrapper" key={year}>
<HeatMapWidget
title={`${year} ${!!data.years.find((e) => e.year === year) &&
data.years.find((e) => e.year === year).total} contributions`} //圖表title
chartData={groupData[year]}
/>
</div>
));
}, [data]);
這樣一來我們就能夠產生基本的熱力圖囉~為了加強使用者效果,我們可以加上一些loading動畫與error catch,並在找不到資料時給一些提示。
今天的東西有點多,詳細可以看commit:
https://github.com/yuanchen1103/2020ironman-github-contributions/commit/8aa1143b4fe037c2d3917e588b044de168d0ccf3